import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:intl/intl.dart';
import '../utils/request.dart';
import '../model/response.dart';
import '../model/notes_character_vo.dart';

/// 自定义异常：角色创建中
class CharacterCreatingException implements Exception {
  final String message;
  CharacterCreatingException(this.message);
  
  @override
  String toString() => message;
}

/// SillyTavern API服务类
/// 使用项目统一的Request类进行API调用，自动携带token
class SillyTavernService {
  static const String prefix = "/aichat";
  
  String? _csrfToken;

  /// 获取CSRF Token
  Future<void> fetchCsrfToken() async {
    try {
      final response = await Request().request(
        "$prefix/csrf-token",
        method: DioMethod.get,
      );
      
      _csrfToken = response['token'];
      print('CSRF Token obtained: $_csrfToken');
    } catch (e) {
      print('Error fetching CSRF token: $e');
      rethrow;
    }
  }

  /// 获取请求的额外Headers（包含CSRF Token）
  Map<String, dynamic> _getCsrfHeader() {
    if (_csrfToken == null) {
      throw Exception('CSRF token not initialized. Call fetchCsrfToken() first.');
    }
    return {'X-CSRF-Token': _csrfToken!};
  }

  /// 获取笔记角色（从后端自动提取和创建）
  /// [notesId] 笔记ID
  /// 返回该笔记的所有角色，如果不存在则后端会自动提取创建
  Future<List<NotesCharacterVO>> getNotesCharacters(String notesId) async {
    try {
      print('🔍 获取笔记 $notesId 的角色列表...');
      
      final response = await Request().request(
        "/notes/character/$notesId",
        method: DioMethod.get,
      );

      print('📦 原始响应: $response');

      // 处理统一返回格式 Result<List<NotesCharacterVO>>
      if (response is Map<String, dynamic>) {
        final code = response['code'];
        final data = response['data'];
        
        if (code == 20010 && data != null) {
          if (data is List) {
            // 调试：打印第一个角色的原始数据类型
            if (data.isNotEmpty) {
              final firstItem = data[0] as Map<String, dynamic>;
              print('🔍 调试信息 - 第一个角色的字段类型:');
              print('   id: ${firstItem['id']} (${firstItem['id'].runtimeType})');
              print('   notesId: ${firstItem['notesId']} (${firstItem['notesId'].runtimeType})');
              if (firstItem['characterImportance'] != null) {
                print('   characterImportance: ${firstItem['characterImportance']} (${firstItem['characterImportance'].runtimeType})');
              }
            }
            
            final characters = data
                .map((json) => NotesCharacterVO.fromJson(json as Map<String, dynamic>))
                .toList();
            
            print('✅ 成功获取 ${characters.length} 个角色');
            
            // 打印新创建的角色
            final newCharacters = characters.where((c) => c.isNewCreated == true).toList();
            if (newCharacters.isNotEmpty) {
              print('🆕 新创建了 ${newCharacters.length} 个角色:');
              for (var char in newCharacters) {
                print('   - ${char.characterName} (${char.characterRole})');
              }
            }
            
            return characters;
          }
        }
        
        // ========== 检查角色创建中的状态 ==========
        final msg = response['msg'];
        if (msg != null && msg.toString().contains('角色创建中')) {
          print('⏳ AI角色正在创建中，需要等待...');
          throw CharacterCreatingException('AI角色正在创建中，请1分钟后进入页面进行AI聊天');
        }
        // ==========================================
        
        // 如果返回其他错误
        final message = msg ?? '未知错误';
        throw Exception('$message');
      }

      throw Exception('Unexpected response format: $response');
    } catch (e) {
      print('❌ 获取笔记角色失败: $e');
      rethrow;
    }
  }

  /// 获取所有角色（已废弃，使用 getNotesCharacters 替代）
  @Deprecated('使用 getNotesCharacters 替代')
  Future<List<STCharacter>> getAllCharacters() async {
    try {
      final response = await Request().request(
        "$prefix/api/characters/all",
        method: DioMethod.post,
        data: {}, // 空对象作为body
        options: Options(
          headers: _getCsrfHeader(),
          method: 'POST', // 明确指定POST方法
        ),
      );

      if (response is List) {
        return response.map((json) => STCharacter.fromJson(json)).toList();
      }
      throw Exception('Unexpected response format');
    } catch (e) {
      print('Error loading characters: $e');
      rethrow;
    }
  }

  /// 获取角色的所有会话
  Future<List<dynamic>> getCharacterChats(String avatarUrl) async {
    try {
      final response = await Request().request(
        "$prefix/api/characters/chats",
        method: DioMethod.post,
        data: {'avatar_url': avatarUrl},
        options: Options(
          headers: _getCsrfHeader(),
          method: 'POST', // 明确指定POST方法
        ),
      );

      if (response is List) {
        // 返回原始对象列表，而不是转换为字符串
        return response;
      }
      return [];
    } catch (e) {
      print('Error loading chats: $e');
      return [];
    }
  }
  
  /// 从会话对象中提取文件名
  String extractFileName(dynamic chat) {
    if (chat is String) {
      return chat;
    } else if (chat is Map) {
      return chat['file_name']?.toString() ?? '';
    }
    return '';
  }

  /// 加载聊天历史
  Future<List<STMessage>> loadChatHistory(
    String avatarUrl,
    String fileName,
  ) async {
    try {
      final response = await Request().request(
        "$prefix/api/chats/get",
        method: DioMethod.post,
        data: {
          'avatar_url': avatarUrl,
          'file_name': fileName,
        },
        options: Options(
          headers: _getCsrfHeader(),
          method: 'POST', // 明确指定POST方法
        ),
      );

      if (response is List) {
        return response.map((json) => STMessage.fromJson(json)).toList();
      }
      return [];
    } catch (e) {
      print('Error loading chat history: $e');
      return [];
    }
  }

  /// 保存聊天记录（完整历史）
  Future<bool> saveChatHistory(
    String avatarUrl,
    String fileName,
    List<STMessage> messages,
  ) async {
    try {
      await Request().request(
        "$prefix/api/chats/save",
        method: DioMethod.post,
        data: {
          'avatar_url': avatarUrl,
          'file_name': fileName,
          'chat': messages.map((m) => m.toJson()).toList(),
        },
        options: Options(
          headers: _getCsrfHeader(),
          method: 'POST', // 明确指定POST方法
        ),
      );

      print('Chat saved successfully');
      return true;
    } catch (e) {
      print('Error saving chat: $e');
      return false;
    }
  }

  /// ========== 批量保存新消息 ==========
  /// 保存新增的消息到现有会话
  Future<bool> saveNewMessages(
    String avatarUrl,
    String fileName,
    List<STMessage> newMessages,
  ) async {
    if (newMessages.isEmpty) {
      print('⏭️ 没有新消息需要保存');
      return true;
    }

    try {
      print('💾 批量保存 ${newMessages.length} 条消息...');

      // 方案1: 尝试调用后端追加接口
      try {
        await Request().request(
          "$prefix/api/chats/append",
          method: DioMethod.post,
          data: {
            'avatar_url': avatarUrl,
            'file_name': fileName,
            'messages': newMessages.map((m) => m.toJson()).toList(),
          },
          options: Options(
            headers: _getCsrfHeader(),
            method: 'POST',
          ),
        );

        print('✅ 批量保存成功（追加模式）');
        return true;
      } catch (e) {
        // 如果追加接口不存在，使用合并方案
        print('⚠️ 追加接口不可用，使用合并方案');
        return await _saveByMerging(avatarUrl, fileName, newMessages);
      }
    } catch (e) {
      print('❌ 批量保存失败: $e');
      return false;
    }
  }

  /// 降级方案：读取现有历史并合并保存
  Future<bool> _saveByMerging(
    String avatarUrl,
    String fileName,
    List<STMessage> newMessages,
  ) async {
    try {
      // 1. 读取现有历史
      final existingMessages = await loadChatHistory(avatarUrl, fileName);
      print('📖 读取现有消息: ${existingMessages.length} 条');

      // 2. 合并消息（去重）
      final allMessages = [...existingMessages];
      for (var newMsg in newMessages) {
        // 根据时间戳去重
        if (!allMessages.any((m) => m.sendDate == newMsg.sendDate)) {
          allMessages.add(newMsg);
        }
      }

      print('📝 合并后总计: ${allMessages.length} 条');

      // 3. 保存完整历史
      final success = await saveChatHistory(avatarUrl, fileName, allMessages);
      
      if (success) {
        print('✅ 批量保存成功（合并模式）');
      }
      
      return success;
    } catch (e) {
      print('❌ 合并保存失败: $e');
      return false;
    }
  }
  // ================================

  /// 查找或创建用户会话
  /// 
  /// 使用用户 ID 作为会话标识，自动查找该用户的现有会话或创建新的
  /// 
  /// - [avatarUrl]: 角色头像 URL
  /// - [characterName]: 角色名称
  /// - [userId]: 用户 ID
  /// - [userName]: 用户名称
  /// 
  /// 返回会话文件名
  Future<String> findOrCreateUserChat(
    String avatarUrl,
    String characterName,
    String userId,
    String userName,
  ) async {
    try {
      print('🔍 查找用户 $userId 与角色 $characterName 的会话');
      
      // 获取该角色的所有会话
      final allChats = await getCharacterChats(avatarUrl);
      print('📋 角色共有 ${allChats.length} 个会话');
      
      // ========== 修复：添加 .jsonl 后缀 ==========
      // 使用用户 ID 作为会话名（确保唯一性），添加 .jsonl 后缀
      final userChatName = 'user_${userId}.jsonl';
      final userChat = 'user_${userId}';
      // =========================================
      
      // 检查是否已存在该用户的会话
      bool foundExisting = false;
      for (var chat in allChats) {
        final fileName = extractFileName(chat);
        print('🔍 比较会话: $fileName vs $userChatName');
        if (fileName == userChatName) {
          foundExisting = true;
          print('✅ 找到现有会话: $userChatName');
          break;
        }
      }
      
      if (foundExisting) {
        return userChat;
      }
      
      // 不存在则创建新会话
      print('🆕 创建新会话: $userChat');
      return await _createUserChat(avatarUrl, characterName, userId, userName, userChat);
      
    } catch (e) {
      print('❌ 查找或创建会话失败: $e');
      rethrow;
    }
  }

  /// 创建用户会话（内部方法）
  Future<String> _createUserChat(
    String avatarUrl,
    String characterName,
    String userId,
    String userName,
    String chatName,
  ) async {
    // 创建初始会话（只包含元数据）
    final initialChat = [
      STMessage.metadata(
        userName: userName,
        characterName: characterName,
        createDate: DateFormat('yyyy-MM-dd @HH:mm:ss').format(DateTime.now()),
      ),
    ];

    // 保存新会话
    final success = await saveChatHistory(avatarUrl, chatName, initialChat);

    if (success) {
      print('✅ 会话创建成功: $chatName');
      return chatName;
    } else {
      throw Exception('Failed to create user chat');
    }
  }

  /// 创建新会话（已废弃，保留向后兼容）
  @Deprecated('Use findOrCreateUserChat instead')
  Future<String> createNewChat(
    String avatarUrl,
    String characterName,
    String userName,
  ) async {
    // ========== 修复：添加 .jsonl 后缀 ==========
    // 使用时间戳作为会话名，添加 .jsonl 后缀
    final timestamp = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
    final chatName = '$timestamp.jsonl';
    // =========================================

    // 创建初始会话（只包含元数据）
    final initialChat = [
      STMessage.metadata(
        userName: userName,
        characterName: characterName,
        createDate: DateFormat('yyyy-MM-dd @HH:mm:ss').format(DateTime.now()),
      ),
    ];

    // 保存新会话
    final success = await saveChatHistory(avatarUrl, chatName, initialChat);

    if (success) {
      return chatName;
    } else {
      throw Exception('Failed to create new chat');
    }
  }

  /// 生成AI回复（非流式）
  Future<String> generateReply({
    required List<STMessage> chatHistory,
    required String systemPrompt,
    double temperature = 0.7,
    int maxTokens = 500,
  }) async {
    try {
      // 构建消息列表
      final messages = [
        {'role': 'system', 'content': systemPrompt},
        ...chatHistory
            .where((m) => !m.isMetadata) // 过滤元数据
            .map((m) => {
                  'role': m.isUser ? 'user' : 'assistant',
                  'content': m.mes,
                }),
      ];

      final response = await Request().request(
        "$prefix/api/backends/chat-completions/generate",
        method: DioMethod.post,
        data: {
          'messages': messages,
          'model': 'deepseek-v3.1',
          'temperature': temperature,
          'max_tokens': maxTokens,
          'stream': false,
          'chat_completion_source': 'custom',
          'custom_url': 'https://newapi.ashesb.com/v1',
        },
        //[aws]claude-opus-4-20250514
        options: Options(
          headers: _getCsrfHeader(),
          method: 'POST', // 明确指定POST方法
        ),
        reactiveTime: const Duration(seconds: 60),
      );

      if (response is Map && response.containsKey('choices')) {
        return response['choices'][0]['message']['content'];
      }
      throw Exception('Unexpected response format: $response');
    } catch (e) {
      print('Error generating reply: $e');
      rethrow;
    }
  }
}

/// 消息模型
class STMessage {
  final String name;
  final bool isUser;
  final int sendDate; // Unix时间戳（毫秒）
  final String mes;

  // 元数据字段（仅第一条消息使用）
  final String? userName;
  final String? characterName;
  final String? createDate;
  final Map<String, dynamic>? chatMetadata;

  STMessage({
    required this.name,
    required this.isUser,
    required this.sendDate,
    required this.mes,
    this.userName,
    this.characterName,
    this.createDate,
    this.chatMetadata,
  });

  /// 创建元数据消息（会话的第一条消息）
  factory STMessage.metadata({
    required String userName,
    required String characterName,
    required String createDate,
    Map<String, dynamic>? chatMetadata,
  }) {
    return STMessage(
      name: '',
      isUser: false,
      sendDate: DateTime.now().millisecondsSinceEpoch,
      mes: '',
      userName: userName,
      characterName: characterName,
      createDate: createDate,
      chatMetadata: chatMetadata ?? {'note_prompt': '', 'note_interval': 0},
    );
  }

  /// 创建用户消息
  factory STMessage.user({
    required String name,
    required String content,
  }) {
    return STMessage(
      name: name,
      isUser: true,
      sendDate: DateTime.now().millisecondsSinceEpoch,
      mes: content,
    );
  }

  /// 创建AI消息
  factory STMessage.assistant({
    required String name,
    required String content,
  }) {
    return STMessage(
      name: name,
      isUser: false,
      sendDate: DateTime.now().millisecondsSinceEpoch,
      mes: content,
    );
  }

  factory STMessage.fromJson(Map<String, dynamic> json) {
    return STMessage(
      name: json['name'] ?? '',
      isUser: json['is_user'] ?? false,
      sendDate: json['send_date'] ?? DateTime.now().millisecondsSinceEpoch,
      mes: json['mes'] ?? '',
      userName: json['user_name'],
      characterName: json['character_name'],
      createDate: json['create_date'],
      chatMetadata: json['chat_metadata'],
    );
  }

  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{
      'name': name,
      'is_user': isUser,
      'send_date': sendDate,
      'mes': mes,
    };

    if (userName != null) json['user_name'] = userName;
    if (characterName != null) json['character_name'] = characterName;
    if (createDate != null) json['create_date'] = createDate;
    if (chatMetadata != null) json['chat_metadata'] = chatMetadata;

    return json;
  }

  /// 判断是否为元数据消息
  bool get isMetadata => userName != null && characterName != null;

  /// 格式化发送时间
  String get formattedTime {
    final date = DateTime.fromMillisecondsSinceEpoch(sendDate);
    return DateFormat('HH:mm').format(date);
  }
}
